<?php
/**
 * Copyright (c) [2019] [selibra]
 * [吴跃忠] is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 * http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 */

namespace Selibra\MQ;


use AMQPChannel;
use AMQPConnection;
use AMQPExchange;
use Co\System;
use Selibra\Config\Config;
use Selibra\MQ\Intf\ProducerInterface;
use Selibra\Tools\Console;
use Swoole\Coroutine;

class Producer implements ProducerInterface
{

    protected $channel;

    /**
     * Producer constructor.
     * @throws \AMQPConnectionException
     * @throws \AMQPExchangeException
     */
    public function __construct()
    {
        $config = Config::get('rabbitmq.connect');
        $arr = [
            'host' => $config['host'],
            'port' => $config['port'],
            'user' => $config['user'],
            'password' => $config['password'],
            'vhost' => $config['vhost'],
        ];
        //构造函数   AMQPConnection
        $con = $this->getConnect($arr);

        //先通道声明--传入连接的套接字--构造函数 通过通道连接创建消息通道
        $this->channel = new AMQPChannel($con);
    }


    /**
     * @param $config
     * @return AMQPConnection
     * @throws \AMQPConnectionException
     */
    protected function getConnect($config)
    {

        try {
            $connect = new AMQPConnection($config);
            $connect->connect();
        } catch (\AMQPConnectionException $exception) {
            // 重新连接
            Coroutine::sleep(5);
            return $this->getConnect($config);
        }
        return $connect;
    }


    /**
     * @inheritDoc
     * @throws
     */
    public function send(string $message, string $routing, int $priority = MQConsts::PRIORITY_LOW)
    {
        //交换机声明--传入声明的通道-- 构造函数 通过通道连接交换机
        $exchange = new AMQPExchange($this->channel);

        //设置交换机名
        $exchange->setName($routing);

        $exchange->setType(AMQP_EX_TYPE_DIRECT);
        $exchange->publish($message, $routing, AMQP_NOPARAM, [
            'delivery_mode' => AMQP_DURABLE,
            'priority' => $priority
        ]);
    }
}